#ifndef _PARTICLE_CIRCLE_H_
#define _PARTICLE_CIRCLE_H_

#include <vector>
#include <algorithm>
#include <string>
#include <iostream>
#include <fstream>
#include <cmath>

#ifdef WIN32
#include <Windows.h>
#endif
#include <GL/GL.h>

#include <boost/math/constants/constants.hpp>

#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Circle_2.h>
#include <CGAL/Aff_transformation_2.h>

#include "error_info.h"

namespace Packing_common
{
	using namespace Packing_common;

	class Particle_circle : public CGAL::Circle_2<CGAL::Exact_predicates_inexact_constructions_kernel> 
	{
		typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
		
		typedef K::Segment_2 Segment_2;
		
		typedef CGAL::Circle_2<K>	CGAL_Circle_2;

	public:
		typedef K::Point_2 Point_2;
		typedef K::Vector_2 Vector_2;

	public:
		Particle_circle() : CGAL_Circle_2(Point_2(0.0, 0.0), 0.0) {}

		Particle_circle(const Point_2& center, double squared_radius) : CGAL_Circle_2(center, squared_radius) 
		{
			rad = std::sqrt(squared_radius);
			vec = Vector_2(0.0, 0.0);
		}

		double radius() const { return rad; }
	
		void translate(double tx, double ty);

		void gl_draw(const GLfloat *fill_color) const;

		Vector_2 orientation_vector() const { return vec; }
		inline void orientation_vector(const Vector_2& v) { vec = v; }

	private:
		double rad;
		Vector_2 vec; // orientation vector
	};

	template <class BackInsertIter>
	BackInsertIter read_circles(const std::string& circle_fn, BackInsertIter res)
	{
		std::ifstream fin(circle_fn.c_str());
		if (!fin.is_open())
			throw Bad_input("Circle file cannot be openned.\n");
		unsigned int nb_circles;
		if (!(fin >> nb_circles))
			throw Bad_input("Bad format in the input file.");
		for (unsigned int i = 0; i < nb_circles; i++)
		{
			double cx, cy, squared_radius;
			if (!(fin >> cx))
				throw Bad_input("Bad format in the input file.");
			if (!(fin >> cy))
				throw Bad_input("Bad format in the input file.");
			if (!(fin >> squared_radius))
				throw Bad_input("Bad format in the input file.");
			if (squared_radius < 0.0)
				throw Bad_input("Square of radius must be nonnegative!");
			*res++ = Particle_circle(Particle_circle::Point_2(cx, cy), squared_radius);
		}

		return res;
	}

	Particle_circle centralized_transform(const Particle_circle& c, /*const Particle_circle::Point_2& ref_pnt,*/ double theta, double tx, double ty); 
}

#endif